﻿using System.ComponentModel;
using System.Runtime.Serialization;

namespace NthDownload.Contracts
{
    public class DownloadSegment : INotifyPropertyChanged
    {
        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion INotifyPropertyChanged

        #region Class Members

        private long _startPosition;
        private long _currentPosition;
        private long _endPosition;

        #endregion Class Members

        #region Constructors

        /// <summary>
        /// Used to represend part of a download
        /// </summary>
        public DownloadSegment()
        {
            //
            // Assign default values
            //
            _startPosition = 0;
            _currentPosition = 0;
            _endPosition = 0;
        }

        #endregion Constructors

        #region Properties

        /// <summary>
        /// Start position of the segment
        /// </summary>
        public long StartPosition 
        {
            get
            {
                return _startPosition;
            }
            set
            {
                _startPosition = value;
                OnPropertyChanged("StartPosition");
            }
        }

        /// <summary>
        /// The position up to which this segment has been downloaded
        /// </summary>
        public long CurrentPosition
        {
            get
            {
                return _currentPosition;
            }
            set
            {
                _currentPosition = value;
                OnPropertyChanged("CurrentPosition");
                OnPropertyChanged("Size");
                OnPropertyChanged("SizeRemaining");
                OnPropertyChanged("IsFinished");
            }
        }
        
        /// <summary>
        /// End position of the segment
        /// </summary>
        public long EndPosition
        {
            get
            {
                return _endPosition;
            }
            set
            {
                _endPosition = value;
                OnPropertyChanged("EndPosition");
                OnPropertyChanged("Size");
                OnPropertyChanged("SizeRemaining");
                OnPropertyChanged("EndPosition");
                OnPropertyChanged("IsFinished");
            }
        }

        /// <summary>
        /// Size of the segment
        /// </summary>
        public long Size
        {
            get
            {
                return (EndPosition < 0) ? 0 : EndPosition + 1 - StartPosition;
            }
        }

        /// <summary>
        /// Size remaining to download
        /// </summary>
        public long SizeRemaining
        {
            get
            {
                return (EndPosition < 0) ? 0 : EndPosition + 1 - CurrentPosition;
            }
        }

        /// <summary>
        /// Indicates if the segment is infinite. A segment is considered inifite when the end position is less than zero.
        /// When an infinite segment completes downloading it's end position is set. It therefore stop being infinite
        /// but will now be marked and complete and have a size.
        /// </summary>
        public bool IsInfinite
        {
            get
            {
                return EndPosition < 0;
            }
        }

        /// <summary>
        /// Indicates if the segment has been fully downloaded.
        /// </summary>
        public bool IsFinished
        {
            get
            {
                return (EndPosition < 0) ? false : CurrentPosition >= EndPosition;
            }
        }

        #endregion Properties
    }
}
